/***************************************************************************
simple.cpp  
-------------------
begin                : Fri May 31 00:53:11 CEST 2002
copyright            : (C) 2002-2003 by Manuel Astudillo
email                : d00mas@efd.lth.se
***************************************************************************/

/***************************************************************************
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU Lesser General Public License as        *
*   published by the Free Software Foundation; either version 2 of the    *
*   License, or (at your option) any later version.                       *
*                                                                         *
***************************************************************************/

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "CGTFile.h"
#include "simpleErrorRep.h"
using namespace std;

char *load_source (char *filename);
void printTokens (vector <Token*> &t);
void del_comment(char* filename);

#define IN_START 0;
#define IN_SINGLE_QUOTE 1;
#define IN_DOUBLE_QUOTE 2;
#define IN_ONE_SLASH 3;
#define IN_LINE_COMMENT 4;
#define IN_BLOCK_COMMENT 5;
#define LEAVING_BLOCK_COMMENT 6;


int main(int argc, char *argv[])
{
	CGTFile    cgtFile;
	char       *source;
	Symbol     *rdc;
	DFA        *dfa;
	LALR       *lalr;

	ErrorTable       *myErrors;
	SimpleErrorRep   myReporter; 

	// Load grammar file
	//if (cgtFile.load ("simple.cgt")) {
	if (cgtFile.load ("JavaScript.cgt")) {
		printf ("%s\n", "Grammar loaded succesfully");
		cgtFile.printInfo ();
	} else {
		wprintf (L"%s\n", "error loading file");
		return -1;
	}

	// Load source file
	char *filename = "benchmark/test.js";
	del_comment(filename);
	char *del_comment_file = "after_del_comment_test.js";
	source = load_source (del_comment_file);
	if (source == NULL) {
		wprintf (L"Error loading source file\n");
		return -1;
	}

	// Get DFA (Deterministic Finite Automata) from the cgt file
	dfa = cgtFile.getScanner();

	// Scan the source in search of tokens
	dfa->scan(source);

	delete [] source;

	// Get the error table
	myErrors = dfa->getErrors();

	// If there are errors report them
	if (myErrors->errors.size() > 0) {
		for (int i=0; i < myErrors->errors.size(); i++) {
			cout << filename << ":";
			cout << myReporter.composeErrorMsg (*myErrors->errors[i]) << endl;
		}
		return -1;
	}

	// Get the tokens to feed the LALR machine with them
	vector <Token*> tokens = dfa->getTokens();
	printTokens (tokens);

	// Get the LALR (Look Ahead, Left-to-right parse, Rightmost-derivation)
	lalr = cgtFile.getParser();

	// Parse the tokens
	rdc = lalr->parse (tokens, true, true);

	myErrors = lalr->getErrors(); 
	if (myErrors->errors.size() != 0) {
		for (int i=0; i < myErrors->errors.size(); i++) {
			cout << filename << ":";
			cout << myReporter.composeErrorMsg (*myErrors->errors[i]) << endl;
		}
		return -1;
	}

	lalr->printReductionTree(rdc, 0);

	/*FILE* file;
	if( (file = fopen("test1.javascript","w")) == NULL )
		cout<<"error opening file!"<<endl;
	else
	{
		lalr->WriteBackReductionTree(rdc,file);
	}*/
	wofstream fos;
	fos.open("benchmark/result.js");
	srand((int)time(0));
	lalr->WriteBackReductionTree(rdc,fos);
	fos.close();

	delete rdc;

	return EXIT_SUCCESS;
}


void printTokens (vector <Token*> &t) {
	for (integer i = 0; i < t.size(); i++) {
		wchar_t *pwe = t[i]->symbol;	
		wprintf (t[i]->symbol);
		wprintf (L":");
		wprintf (t[i]->image);
		wprintf (L"\n");
	}
}

char *load_source (char *filename) {
	FILE *file =  fopen (filename, "rb");
	if (file == NULL) {
		return NULL;
	}

	fseek (file, 0, SEEK_END);
	int fsize = ftell(file);
	fseek (file, 0, SEEK_SET);

	char *src_code;
	src_code = new char[fsize+1];
	fread (src_code, 1, fsize, file);
	src_code[fsize] = 0;

	fclose (file);
	return src_code;
}

void del_comment(char* filename)
{
	FILE* file1 = fopen (filename, "rb");
	char *del_comment_file = "after_del_comment_test.js";
	FILE* file2 = fopen (del_comment_file, "w");

	char c;
	int state = IN_START;
	while( (c=fgetc(file1)) != -1)
	{
		
		//fputc(c,file2);
		switch(state)
		{
		case 0/*IN_START*/:	
			{
				if(c == '\'')
				{
					fputc(c,file2);
					state = 1;
				}
				else if(c == '\"')
				{
					fputc(c,file2);
					state = 2;
				}
				else if(c == '/')
					state = 3;
				else
					fputc(c,file2);
				break;
			}
		case 1/*IN_SINGLE_QUOTE*/:
			{
				if(c == '\'')
					state = 0;
				fputc(c,file2);
				break;
			}
		case 2/*IN_DOUBLE_QUOTE*/:
			{
				if(c == '\"')
					state = 0;
				fputc(c,file2);
				break;
			}
		case 3/*IN_ONE_SLASH*/:
			{
				if(c == '/')
					state = 4;
				else if(c == '*')
					state = 5;
				else
				{
					state = 0;
					fputc('/',file2);
					fputc(c,file2);
				}
				break;
			}
		case 4/*IN_LINE_COMMENT*/:
			{
				if(c == 0x0D)
				{
					state = 0;
					fputc(c,file2);
				}
				break;
			}

		case 5/*IN_BLOCK_COMMENT*/:
			{
				if(c == '*')
					state = 6;
				break;
			}
		case 6/*LEAVING_BLOCK_COMMENT*/:
			{
				if(c == '/')
					state = 0;
				else
					state = 5;
				break;
			}
		
		}
	}

	fclose(file1);
	fclose(file2);
	
}